/**
 * @file CPvmCommands.hpp Deklarácia triedy CPvmCommands.
 *
 * @author Martin Kosorinský.
 * @date 10.10.2009.
 */

#include "miraclExtensions.hpp"
#include "pvm3.h"

#ifndef CPVMCOMMANDS_HEADER
#define CPVMCOMMANDS_HEADER

/**
 * @brief Kapacita buffera pre prevody dátových typov @c big do a z poľa bajtov.
 */
#define BYTE_BUFFER_SIZE       256

/**
 * @brief Trieda zapúzdrujúca komunikačné PVM príkazy spoločné pre server aj klienta.
 */
class CPvmCommands  {
protected:
    /**
     * @brief Kódy pre označenie znamienka prenášaného celého čísla typu @c big.
     */
    enum pvmBigSign {
        PVM_BIG_POSITIVE,    /**< Prenášané číslo je kladné. */
        PVM_BIG_NEGATIVE     /**< Prenášané číslo je záporné. */
    };
public:
    /**
     * @brief Kódy pre označenie prenášaných správ.
     */
    enum pvmMsgType {
        PVM_ECDLP_TASKPOINT, /**< Správa obsahuje súradnice bodu, ktorého diskrétny logaritmu hľadáme (2 čísla typu @c big). */
        PVM_ECDLP_ECPARAMS,  /**< Správa obsahuje parametre krivky a súradnice jej generátora (6 čísiel typu @c big). */
        PVM_ECDLP_DISTPOINT, /**< Správa obsahuje distinguished point (4 čísla typu @c big). */
        PVM_ECDLP_DL,        /**< Správa obsahuje hľadaný diskrétny logaritmus (1 číslo typu @c big). */
        PVM_ECDLP_RESTART,   /**< Signál na reštartovanie výpočtu. */
        PVM_ECDLP_STOP,      /**< Signál na zastavenie výpočtu. */
        PVM_ECDLP_EXIT,      /**< Signál informujúci o ukončení programu (aj neočakávanom). */
    };
    /**
     * @brief Procedúra pripravujúca premenné typu @c big do PVM message bufferu.
     * Pred odoslaním dát prostredníctvom knižnice PVM je nevyhnutné skopírovať dáta do špeciálneho
     * message bufferu. Za týmto účelom využíva procedúra funkcie knižnice PVM, transformácia typu
     * @c big je vykonaná pomocou procedúry big_to_bytes knižnice @c MIRACL.
     * Dáta sú odoslané v nasledovnej štruktúre (pre 1 @c big): <sign: 1B> <size: 4B> <bytes: size*1B>.
     * @param[in] bp Je pole premenných typu @c big, ktoré chceme uložiť do bufferu.
     * @param[in] nitem Počet prvkov, ktoré chceme uložiť do bufferu.
     * @param[in] stride Interval, s ktorým vyberáme prvky (1 = každý prvok, 2 = každý druhý prvok poľa, ...).
     */
    static void pvmPackBig(big * bp, int nitem, int stride);
    /**
     * @brief Procedúra extrahujúca premenné typu @c big z PVM message bufferu.
     * Po prijatí dát prostredníctvom knižnice PVM je nevyhnutné extrahovať dáta zo špeciálneho
     * message bufferu. Extrahovanie premenných typu @c big zabezpečuje táto procedúra. Využíva funkcie
     * knižnice PVM, transformácia poľa bitov na premenné typu @c big je vykonaná pomocou procedúry bytes_to_big.
     * Po prijatí je upravené znamienko čísla v závislosti od prijatého kódu.
     * @param[out] bp Je pole premenných typu @c big (vopred alokované), do ktorého uložíme extrahované dáta.
     * @param[in] nitem Počet prvkov, ktoré chceme extrahovať z bufferu.
     * @param[in] stride Interval, s ktorým vkladáme prvky do poľa @a bp (2: vyberieme postupne každý prvok message
     * bufferu, a postupne ich ukladáme na každé druhé miesto v poli).
     */
    static void pvmUnpackBig(big * bp, int nitem, int stride);
    /**
     * @brief Procedúra zapezpečujúca prijatie PVM správ.
     * Funkcia za pomoci @c pvm_recv() príjme správu a jej kódové označenie vráti ako návratovú hodnotu.
     * Funkcia je blokovaná do prijatia prvej správy od požadovaného odosielateľa.
     * @param[in] tid Identifikátor odosielateľa správy, -1 ak na odosielateľovi nezáleží.
     * @param[in] msg Identifikátor typu správy, -1 ak na type nezáleží.
     * @return Návratovou hodnotou je kód prijatej správy typu #pvmMsgType.
     */
    static int pvmRecv(int tid, int msg);
};
#endif /* CPVMCOMMANDS_HEADER */
